#include "./../../../include/online/RecommendWords/KeyRecommender.h"
#include "./../../../include/online/RecommendWords/Dictionary.h"
#include "./../../../include/online/CacheSystem/CacheManager.h"
#include "./../../../include/online/CacheSystem/LRUCache.h"
#include "./../../../include/online/Tools/MyLogger.h"
#include <string>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <nlohmann/json.hpp>

__thread const char *name;

using nlohmann::json;
using std::string;

vector<string> read_utf8_onebyone(string word)
{
    vector<string> words;
    string input(word);
    int len = input.length();
    int i = 0;

    while (i < len)
    {
        assert((input[i] & 0xF8) <= 0xF0);
        int next = 1;
        if ((input[i] & 0x80) == 0x00)
        {
            std::cout << "one character: " << input[i] << std::endl;
        }
        else if ((input[i] & 0xE0) == 0xC0)
        {
            next = 2;
            std::cout << "two character: " << input.substr(i, next) << std::endl;
        }
        else if ((input[i] & 0xF0) == 0xE0)
        {
            next = 3;
            std::cout << "three character: " << input.substr(i, next) << std::endl;
        }
        else if ((input[i] & 0xF8) == 0xF0)
        {
            next = 4;
            std::cout << "four character: " << input.substr(i, next) << std::endl;
        }
        words.push_back(input.substr(i, next));
        i += next;
    }
    return words;
}

KeyRecommender::KeyRecommender(const string &query)
: _queryWord(query)
{
}

json KeyRecommender::repstr()
{
    json j;
    if (CacheManager::getInstance()->getKeyCache(atoi(name)).getjson(_queryWord, j))
    {
        LogInfo("关键字查询在缓存中命中");
        cout << "该单词走的缓存" << endl;
        return j;
    }
    else
    {
        execute();
        j = response();
        CacheManager::getInstance()->getKeyCache(atoi(name)).put_insert(_queryWord, j);
        cout << "该单词走的查询" << endl;
        LogInfo("对关键字进行查询");
        return j;
    }
}

void KeyRecommender::execute()
{
    queryIndexTable();
}

void KeyRecommender::queryIndexTable()
{
    // 把需要查询的进行一个一个分词放到数组里
    Dictionary* pdict = Dictionary::getInstance();
    if (pdict == nullptr)
    {
        cout << "null" << endl;
    }

    set<int> wordline; // 将来存储的行号集合
    vector<string> chs = read_utf8_onebyone(_queryWord);
    
    if (chs[0].size() < 3)
    {
        unordered_map<string,unordered_set<int>> EnIndexTable = pdict->getEnIndexTable();
        for (auto &ch : chs)
        {
            auto it = EnIndexTable.find(ch); // 在索引库里查找有没有该字符
            if (it != EnIndexTable.end())
            {
                wordline.insert(it->second.begin(), it->second.end());
            }
        }
        cout << wordline.size() << endl;
        statistic(wordline, pdict, 1);
    }
    else
    {      
        unordered_map<string,unordered_set<int>> CnIndexTable = pdict->getCnIndexTable();
        for (auto &ch : chs)
        {
            auto it = CnIndexTable.find(ch); // 在索引库里查找有没有该字符
            if (it != CnIndexTable.end())
            {
                // 将该字符所对应的单词行号插入中间。
                wordline.insert(it->second.begin(), it->second.end());
            }
        }
        cout << wordline.size() << endl;
        statistic(wordline, pdict, 3);
    }
}

void KeyRecommender::statistic(set<int> &iset, Dictionary *pdict, int flag)
{
    
    if (flag == 1)
    {
        vector<pair<string, int>> EnDict = pdict->getEnDict();
        for (auto &it : iset)
        {
            CandidateResult words{};                    // 构建每个单词并且 将单词插入优先队列里。
            words._word = EnDict[it].first;             // 将单词插入
            words._dist = distance(words._word);        // 计算距离
            words._freq = EnDict[it].second;            // 单词词频
            _resultQue.push(words);                     // 将该结构体插入优先队列
        }
    }
    else if(flag = 3)
    {  
        vector<pair<string, int>> CnDict = pdict->getCnDict();
        for (auto &it : iset)
        {
            CandidateResult words{};                        // 构建每个单词并且将单词插入优先队列里。
            words._word = CnDict[it].first;                 // 将单词插入
            words._dist = distance(words._word);            // 计算距离
            words._freq = CnDict[it].second;                // 单词词频
            _resultQue.push(words);                         // 将该结构体插入优先队列
        }
    }
}

int KeyRecommender::distance(const string &rhs)
{
    return editDistance(_queryWord, rhs);
}

json KeyRecommender::response()
{
    vector<string> repjson;
    for (int i = 0; i < 5 && !_resultQue.empty(); ++i)
    {
        cout << _resultQue.top()._word << " "<< _resultQue.top()._dist << " "<< _resultQue.top()._freq << endl;        
       
        repjson.push_back(_resultQue.top()._word);
        _resultQue.pop();
    }

    json j(repjson);
    return j;
}